home *** CD-ROM | disk | FTP | other *** search
/ PC Graphics Unleashed / PC Graphics Unleashed.iso / ch03 / color.c next >
C/C++ Source or Header  |  1993-05-21  |  7KB  |  237 lines

  1. /****************************************************************
  2. * FILE:    color.c
  3. * DESC:    This file contains the color routines used by morph,
  4. *        dissolve and fix.
  5. * HISTORY:    Created     3/18/1993
  6. * LAST CHANGED: 5/ 6/1993
  7. *    Copyright (c) 1992 by Scott Anderson
  8. *
  9. ****************************************************************/
  10.  
  11. #include <stdio.h>
  12. #include <memory.h>
  13.  
  14. #include "define.h"
  15.  
  16. /* ----------------------DEFINES------------------------------ */
  17.  
  18. /* ----------------------TYPEDEFS/STRUCTS--------------------- */
  19.  
  20. /* ----------------------PROTOTYPES--------------------------- */
  21.  
  22. int        closestColor(int r, int g, int b, PALETTE *palPtr);
  23. void    collapseColors(PALETTE *palPtr);
  24. int        mergePalette(PICTURE *pic);
  25. int        remapPicture(PICTURE *picPtr, PALETTE *palPtr);
  26. int        initFreq();
  27.  
  28. /* ----------------------EXTERNALS---------------------------- */
  29.  
  30. /* set from last picture loaded */
  31. extern int        Xmin, Ymin, Xmax, Ymax;
  32.  
  33. /* ----------------------GLOBAL DATA-------------------------- */
  34.  
  35. /* number of colors in tweened image before reduction*/
  36. int     Ncolors;
  37.  
  38. /* r, g, b frequency counter array */
  39. unsigned int far Freq[MAX_COMP][MAX_COMP][MAX_COMP];
  40.  
  41. /* tweened images red, grn, and blu components*/
  42. unsigned char far Red[MAX_WIDE][MAX_TALL];
  43. unsigned char far Grn[MAX_WIDE][MAX_TALL];
  44. unsigned char far Blu[MAX_WIDE][MAX_TALL];
  45.  
  46. PALETTE TweenPal;            /* resulting palette */
  47.  
  48. /*****************************************************************
  49. * FUNC: void    collapseColors(PALETTE *palPtr)
  50. * DESC: Collapse the colors in the Freq table until
  51. *        Ncolors < COLORS, then put it in the given color palette.
  52. *****************************************************************/
  53.  
  54. void
  55. collapseColors(PALETTE *palPtr)
  56. {
  57.     int freqCutoff;
  58.     int r, g, b;
  59.     int index;
  60.     int ncolors;
  61.  
  62.     static int freqCount[MAX_FREQ+1];
  63.  
  64.     memset(freqCount, 0, sizeof freqCount);
  65.     for (r = 0; r < MAX_COMP; r++)
  66.         for (g = 0; g < MAX_COMP; g++)
  67.             for (b = 0; b < MAX_COMP; b++)
  68.                 freqCount[Freq[r][g][b]]++;
  69.  
  70.     ncolors = 0;
  71.     for (freqCutoff = COLORS-1; freqCutoff > 1; freqCutoff--) {
  72.         ncolors += freqCount[freqCutoff];
  73.         if (ncolors > COLORS) break;
  74.     }
  75.  
  76.     /* Collapse color space to 256 colors */
  77.     r = g = b = 0;
  78.     while (Ncolors >= COLORS) {
  79.         for (; r < MAX_COMP; r++, g=0) {
  80.             for (; g < MAX_COMP; g++, b=0) {
  81.                 for (; b < MAX_COMP; b++) {
  82.                     if (Freq[r][g][b] && Freq[r][g][b]
  83.                                                 <= freqCutoff) 
  84.                         goto castOut;    /* the ultimate no no */
  85.                 }
  86.             }
  87.         }
  88.         r = g = b = 0;
  89.         freqCutoff++;
  90.         continue;
  91.     castOut:
  92.         Freq[r][g][b] = 0;    /* just remove this low freq color */
  93.         Ncolors--;
  94.     }
  95.  
  96.     /* build a palette out of all the remaining non zero freq's */
  97.     index = 0;
  98.     for (r = 0; r < MAX_COMP; r++)
  99.         for (g = 0; g < MAX_COMP; g++)
  100.             for (b = 0; b < MAX_COMP; b++)
  101.                 /* we have a color we need to map */
  102.                 if (Freq[r][g][b]) {
  103.                     palPtr->c[index].r = r;
  104.                     palPtr->c[index].g = g;
  105.                     palPtr->c[index].b = b;
  106.                     /* remember index in palette */
  107.                     Freq[r][g][b] = index;
  108.                     index++;
  109.                 }
  110. }
  111.  
  112. /*****************************************************************
  113. * FUNC: int    closestColor(int r, int g, int b, PALETTE *palPtr)
  114. * DESC: return the palette index of the color closest to rgb.
  115. *****************************************************************/
  116.  
  117. int
  118. closestColor(int r, int g, int b, PALETTE *palPtr)
  119. {
  120.     int index;
  121.     int distance;
  122.     int min_distance = 3200;    /* a big number */
  123.     int min_index;
  124.  
  125.     /* The value in Freq is now the index into the color table */
  126.     if (Freq[r][g][b]) return Freq[r][g][b];
  127.  
  128.     /* If zero, search for the closest color */
  129.     for (index = 1; index < Ncolors; index++) {
  130.         /* this is really the distance squared, but it works */
  131.         distance =    SQUARE (r - palPtr->c[index].r) +
  132.                     SQUARE (g - palPtr->c[index].g) +
  133.                     SQUARE (b - palPtr->c[index].b);
  134.         if (distance < min_distance) {
  135.             min_distance = distance;
  136.             min_index = index;
  137.             if (distance <= 2) break;    /* close enough! */
  138.         }
  139.     }
  140.     /* New index - for future reference */
  141.     Freq[r][g][b] = min_index;
  142.     return min_index;
  143. }
  144.  
  145. /*****************************************************************
  146. * FUNC: int    mergePalette(PICTURE *picPtr)
  147. * DESC: Merge a palette into Freq count table.
  148. *****************************************************************/
  149.  
  150. int
  151. mergePalette(PICTURE *picPtr)
  152. {
  153.     int     r, g, b;
  154.     unsigned int     pos;
  155.     unsigned char    index;
  156.     PALETTE *palPtr = &picPtr->pal;
  157.     unsigned char far *bufPtr = picPtr->pixmap;
  158.  
  159.     for (pos = 0; pos < MAX_BYTES; pos++) {
  160.         index = *bufPtr++;
  161.         r = palPtr->c[index].r;
  162.         g = palPtr->c[index].g;
  163.         b = palPtr->c[index].b;
  164.         if (Freq[r][g][b] == 0)        /* A new color */
  165.             Ncolors++;
  166.         if (Freq[r][g][b] < MAX_FREQ)    /* Keep it managable */
  167.             Freq[r][g][b]++;
  168.     }
  169. }
  170.  
  171. /*****************************************************************
  172. * FUNC: int    remapPicture(PICTURE *picPtr, PALETTE *palPtr)
  173. * DESC: Remap a picture with a different palette.
  174. *****************************************************************/
  175.  
  176. int
  177. remapPicture(PICTURE *picPtr, PALETTE *palPtr)
  178. {
  179.     int        x, y;
  180.     int     index;
  181.     int        r, g, b;
  182.     unsigned int    pos;
  183.     unsigned char     lookup[COLORS];
  184.     unsigned char far *bufPtr;
  185.     
  186.     /* Create the cross-reference lookup table */
  187.     for (index = 0; index < COLORS; index++) {
  188.         r = picPtr->pal.c[index].r;
  189.         g = picPtr->pal.c[index].g;
  190.         b = picPtr->pal.c[index].b;
  191.         lookup[index] = closestColor(r, g, b, palPtr);
  192.     }
  193.     
  194.     /* Save the new palette in the picture's palette */
  195.     for (index = 0; index < COLORS; index++) {
  196.         picPtr->pal.c[index].r = palPtr->c[index].r;
  197.         picPtr->pal.c[index].g = palPtr->c[index].g;
  198.         picPtr->pal.c[index].b = palPtr->c[index].b;
  199.     }
  200.  
  201.     /* Remap the individual pixels to point to the new colors */
  202.     for (bufPtr = picPtr->pixmap, pos = 0; pos < MAX_BYTES;
  203.                                                 bufPtr++, pos++)
  204.         *bufPtr = lookup[*bufPtr];
  205. }
  206. /*****************************************************************
  207. * FUNC: int    initFreq()
  208. * DESC: zero out the frequency color space table
  209. *****************************************************************/
  210.  
  211. int
  212. initFreq()
  213. {
  214.     int bytes = (sizeof Freq) / 2;
  215.  
  216.     _fmemset(Freq, 0, bytes);
  217.     /* divide because of element size */
  218.     _fmemset(Freq+(bytes/sizeof *Freq), 0, bytes);
  219.  
  220.     /* Guarantee a black color */
  221.     Freq[0][0][0] = MAX_FREQ;
  222.     /* a grey color */
  223.     Freq[MID_COMP-1][MID_COMP-1][MID_COMP-1] = MAX_FREQ;
  224.     /* and a white color */
  225.     Freq[(long)MAX_COMP-1][MAX_COMP-1][MAX_COMP-1] = MAX_FREQ;
  226.     Ncolors = 3;
  227. }
  228.     
  229.  
  230.